Assembly Language
©
Copyright Brian Brown, 1988-2000. All rights reserved.
| Notes | Home Page |
ASSEMBLY LANGUAGE PROGRAMMING, Part 3
IMPLEMENTATION OF HIGH LEVEL LANGUAGE CONSTRUCTS
In High Level
Languages such as PASCAL and BASIC, several constructs are available which help
to implement programs. You should know how these constructs are implemented in
assembly language.The constructs that we will now deal with involve SELECTION
and ITERATION. Both types of constructs are implemented using the conditional
BRANCH instructions of the processor.
These types of instructions test the state of the various flags of the status register. All variables are memory based. Any manipulation of variables normally involves three steps,
X1 := 20; LDX #20 STX X1
Use eight bit registers for bytes/characters, and 16bit registers for integers. eg,
Letter := 'Y'; LDAA #'Y' STAA Letter
Assigning a variables value to another variable
X1 := Y; LDX Y STX X1
X1 := Y + 7 ; Calculate the right side first. ; Load Y into a register, use an immediate add with 7, ; then store into variable X1 (following example uses ; BYTE integers) LDAA Y ADDA #7 STAA X1 eg, X1 := Y + Z ; Calculate the right side first. Load Y and Z into ; registers, add the two registers together, store the ; result into variable X1. LDAA Y LDAB Z ABA STAA X1 eg, X1 := Y + Z + 3 + T ; Calculate the right hand side first. If the ; number of variables/constants exceed the number of ; registers available, parenthesise and calculate portions ; at a time. Finally, store the result back into the left ; side variable X1. LDAA T ADDA #3 ; 3 + T LDAB Z ABA ; + Z LDAB Y ABA ; + Y STAA X1
X1 := Y - 7 ; Calculate the right side first. Load Y into a register, ; use an immediate subtract with 7, then store into ; variable X1. LDAA Y SUBA #7 STAA X1 eg, X1 := Y - Z ; Calculate the right side first. Load Y and Z into ; registers, subtract the two registers together, store ; the result into variable X1. LDAA Y LDAB Z SBA ; subtract bx from ax, Z from Y STAA X1 eg, X1 := Y - Z - 3 - T ; Calculate the right hand side first. If the ; number of variables/constants exceed the number of ; registers available, parenthesise and calculate portions ; at a time. Finally, store the result back into the left ; side variable X1. Take special note of the order of ; evaluation, in this case Z is subtracted from Y, 3 ; subtracted from that and so on. LDAA Y LDAB Z ABA ; Y - Z SUBA #3 ; - 3 LDAB T SBA ; - T STAA X1
X1 := Y + 4 - Z * 7 ; Calculate the right hand side first. If the ; number of variables/constants exceed the number of registers available, ; parenthesise and calculate portions at a time. Finally, store the result ; back into the left side variable X1. Take special note of the order of ; evaluation, in this case multiplication occurs before addition or ; subtraction. ; The statement can be interpreted as, X1 := (Y + 4) - ( Z * 7 ) ; or X1 := Y + (4 - Z) * 7 ; Assuming that the real intention is the first grouping, first calculate ; the term (Z * 7), then the term (Y + 4), and subtract the first term ; from the second, storing the result into X1. LDAA Z LDAB #7 ; mult A,B ; (Z * 7) LDAB Y ADDB #4 ; (Y + 4) ABA STAA X1 WHERE THE EXPRESSION IS COMPLEX AND INVOLVES A LARGE NUMBER OF TERMS, THIS WILL REQUIRE THE USE OF TEMPORARY STORAGE LOCATIONS FOR STORING INTERMEDIATE RESULTS.
if: ; comparison test ; jump false to endif ; if body statements endif:
IF X1 < 10 then Y := Z * 2; if: LDAA X CMPA #10 BCC endif LDAA Z ; if body, Y := Z * 2 LDAB 2 ; mult a, b STAA Y endif:
IF X1 >= Z then Y := X; if: LDAB Z LDAA X CBA BLT endif LDAA X1 ; if body, Y := X1; STAA Y endif:
IF X1 then Y := X / 2; if: LDAA X CMPA #0 BEQ endif LDAA X1 ; if body, Y:=X1 / 2; LDAB #2 ; div A, B STAA Y endif:
IF X1 then Y := X + 2; if: LDAA X1 CMPA #0 BHI endif LDAA X1 ; if body, Y:=X1 + 2; ADDA #2 STAA Y endif: WHERE THE CONDITION OF THE IF STATEMENT IS EXPRESSED NEGATIVELY, USING A NOT INSTRUCTION, THEN A BRANCH TRUE INSTRUCTION SHOULD BE USED INSTEAD OF A BRANCH FALSE INSTRUCTION. eg, IF X1 = 2 then Y := 4; if: LDAA X1 CMPA #2 BNE endif LDAA #4 STAA Y endif: IF NOT X1 = 2 then Y := 4; if: LDAA X CMPA #2 BEQ endif LDAA #4 STAA Y endif:
if: ; comparison ; branch false to else clause ; if body statements jmp endif else: ; else statements ; endif:
The same principles apply to the various forms that expressions can take. eg,
IF X = 2 THEN Y := Y + 4 ELSE Z := 0; if: LDAA X CMPA #2 BNE else LDAA Y ADDA #4 STAA Y JMP endif else: LDAA #0 STAA Z endif:
while: ; comparison test ; branch false to endwhile ; while body statements jmp while endwhile: WHILE X < 10 DO BEGIN Y := Y + X; X := X + 1 END; while: LDAA X CMPA #10 BHI endwhile LDAB X ; Y := Y + X LDAA Y ABA STAA Y LDAA X ; X := X + 1 ADDA #1 STAA X JMP while endwhile: PREVIOUS RULES CONCERNING NEGATION ALSO APPLY. NOTE THAT ALL PREVIOUS FUNDAMENTALS OF STATEMENT ASSIGNMENT AND TESTING OF VARIABLES AGAINST EACH OTHER OR CONSTANTS ARE STILL BEING RIGIDLY APPLIED.
initfor: ; initialise loop variable for: ; comparison test ; jump false endfor ; for body statements ; adjust loop variable for next step jmp for endfor: FOR X := 1 to 10 do BEGIN Y := Y + X END; initfor: LDAA #1 STAA X for: LDAA X CMPA #10 BHI endfor LDAB X ; Y := Y + X LDAA Y ABA STAA Y LDAA X ; NEXT X ADDA #1 STAA X JMP for endfor: PREVIOUS RULES CONCERNING NEGATION ALSO APPLY. NOTE THAT ALL PREVIOUS FUNDAMENTALS OF STATEMENT ASSIGNMENT AND TESTING OF VARIABLES AGAINST EACH OTHER OR CONSTANTS ARE STILL BEING RIGIDLY APPLIED.
6802 Processor Examples
IF X = 2 THEN Y = X
The compare statement must be coded in such a way as to compare the value of X against the constant 2. As the variable X is stored in memory, the programmer should first load a register with the variable X before making the comparison (because most processors do not support a compare between memory contents and immediate data).This example gets coded as,
X: DFB 10 Y: DFB 00 .... LDAA X ; load A acc with value of X CMPA #02 ; compare A acc with immediate data BNE IF1 ; exit if false LDAA X ; get value of X STAA Y ; store value of X at variable Y IF1: ..... ; next statement after if construct
Lets consider another example.
IF X = Y THEN Y = 0
In this case, the code to be generated by the assembler for the compare statement depends upon the addressing modes available. The options available are,
memory to memory compare CMP [X], [Y] register to memory compare CMPA [Y] register to register compare CMPAB
Both X and Y variables are memory based, so if the processor supports a comparison of two memory operands, it could be coded as,
CMP [X],[Y] ; sample only
However, most processors do not support this. The most common option is the comparison of a register variable against memory contents. This is coded as follows,
LDAA X ; get variable X CMPA Y ; compare with variable Y BNE IF1 ; exit it not equal LDAA #00H ; set variable Y to zero STAA Y IF1: ....
This code can clearly be optimized (ie, some instructions can be removed without affecting the original intent of the code). So far we have considered comparisons for equality. The conditional branch instruction will vary depending upon what type of comparison test is used. The following tables illustrate common comparison tests and their associated conditional branch instructions.
+-----------------+-------------+--------------+ | Signed Operands | Branch True | Branch False | +-----------------+-------------+--------------+ | r > m | BGT | BLE | +-----------------+-------------+--------------+ | r >=m | BGE | BLT | +-----------------+-------------+--------------+ | r = m | BEQ | BNE | +-----------------+-------------+--------------+ | r <=m | BLE | BGT | +-----------------+-------------+--------------+ | r < m | BLT | BGE | +-----------------+-------------+--------------+ If ....... Then ---- Use Branch False If NOT ... Then ---- Use Branch True +-----------------+-------------+--------------+ |UnSigned Operands| Branch True | Branch False | +-----------------+-------------+--------------+ | r > m | BHI | BLS | +-----------------+-------------+--------------+ | r >=m | BCC | BCS | +-----------------+-------------+--------------+ | r = m | BEQ | BNE | +-----------------+-------------+--------------+ | r <=m | BLS | BHI | +-----------------+-------------+--------------+ | r < m | BCS | BCC | +-----------------+-------------+--------------+
The following table represents a cross-reference between branch instructions and the flags they test.
+------+----------------+----------+ | 6802 | Flags Tested | 8088 | +------+----------------+----------+ | BCC | C = 0 | JNB, JAE | +------+----------------+----------+ | BCS | C = 1 | JB, JNAE | +------+----------------+----------+ | BNE | Z = 0 | JNE, JNZ | +------+----------------+----------+ | BEQ | Z = 1 | JE, JZ | +------+----------------+----------+ | BPL | N = 0 | JNS | +------+----------------+----------+ | BMI | N = 1 | JS | +------+----------------+----------+ | BHI | C + Z = 0 | JNBE, JA | +------+----------------+----------+ | BLS | C + Z = 1 | JBE, JNA | +------+----------------+----------+ | BGE | N EOR V = 0 | JNL, JGE | +------+----------------+----------+ | BLT | N EOR V = 1 | JL, JNGE | +------+----------------+----------+ | BGT |Z + (N EOR V)= 0| JG, JNLE | +------+----------------+----------+ | BLE |Z + (N EOR V)= 1| JLE,JNG | +------+----------------+----------+
These tables are useful in determining the correct conditional instruction to use for a particular comparison on specific data types. Coding the following statement applicable to two unsigned 8bit data values
IF X <= Y THEN Y = 4 X: DFB 10H Y: DFB 12H IF: LDAA X CMPA Y BHI IF1 LDAA #04H STAA Y IF1: ....
IF X = 2 THEN Y = X ELSE X = Y
This becomes coded as,
X: DFB 00 Y: DFB 00 IF: LDAA X CMPA #02D BNE ELSE1 LDAA X STAA Y JMP IF1 ELSE1: LDAA Y STAA X IF1: ....
WHILE X < 10 DO Y = Y + 1 X = X + 1 WEND
This becomes coded as,
X: DFB 00H Y: DFB 00H DO1: LDAB X CMPB #10D BCC EXIT1 ; for signed use BLT LDAA Y ; increment value of Y ADDA #01 STAA Y LDAA X ; increment value of X ADDA #01 STAA X JMP DO1 EXIT1: ...
Consider the coding of the following HLL program into 6802 assembler.
Program HLLTest(); var loop, val1, val2 : Byte; Begin val1 := 0; val2 := 0; loop := 0; while loop <= 10 do begin val2 := val2 + loop; loop := loop + 1 end; if val1 < val2 then val1 := val2 else val2 := val1 end.
The 6802 assembler version is
; HLLtest.asm CPU 6802 HOF MOT ORG 100h loop: dfb 0 val1: dfb 0 val2: dfb 0 ORG 120h Begin: LDAA #0 ; val1 := 0 STAA val1 LDAA #0 ; val2 := 0 STAA val2 LDAA #0 ; loop := 0 STAA loop While: LDAA loop ; while loop <= 10 do CMPA #10 BGT if1 LDAA val2 ; val2 := val2 + loop LDAB loop ABA STAA val2 LDAA loop ; loop := loop + 1 ADDA #01 STAA loop JMP While ; endwhile if1: LDAA val2 ; if val1 < val2 then CMPA val1 BGE Else LDAA val2 ; val1 := val2 STAA val1 JMP endif Else: LDAA val1 ; else val2 := val1 STAA Val2 Endif: NOP SWI End Begin